﻿using HarfBuzzSharp;
using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Runtime;
using netDxf.Entities;
using SkiaSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using LightCAD.MathLib;
using Avalonia.Controls;


namespace LightCAD.Drawing.Actions
{
    public class DimArcAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;
        private Vector2 midPoint;
        private Vector2 ArcStart;
        private Vector2 ArcEnd;
        private Vector2 ArcCenter;
        public double ArcStartAngle;
        public double ArcEndAngle;
        public double ArcMoveAngle;
        public double ArcLength;
        
        static DimArcAction()
        {
            CommandName = "DIMARC";
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "DAR",
                Description = "DIMARC",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep{ Name="Step0", Options="选择弧线段或多段线圆弧段:" },
                    new LcCreateStep{ Name="Step1", Options="指定弧长标注位置或 [多行文字(M)/文字(T)/角度(A)/部分(P)/引线(L)]:" },
                }
            };
            
        }

        internal static void Initilize()
        {
            ElementActions.DimArc = new DimArcAction();
            LcDocument.ElementActions.Add(BuiltinElementType.DimArc, ElementActions.DimArc);
        }

        private PointInputer PointInputer { get; set; }
        public DimArcAction() { }
        public DimArcAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令 ：DAR");
        }
        private LcCreateMethod GetMethod(string method)
        {
            if (method == null) return CreateMethods[0];
            var getted= CreateMethods.FirstOrDefault((m) => m.Name == method);
            if (getted == null)
                return CreateMethods[0];
            else
                return getted;
        }
        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            //this.Segments = new List<RolineSegment>();
            var curMethod = SetCurMethod(CreateMethods, 0);
            var ElementInputer = new ElementInputer(this.docEditor);
            this.PointInputer = new PointInputer(this.docEditor);
            Step0:
            var step0 = SetCurStep(curMethod, 0);
            var result0 = await ElementInputer.Execute(step0.Options);
            if (ElementInputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result0.ValueX == null)
            {
                goto Step0;
            }
            else
            {
                LcElement element = (LcElement)result0.ValueX;
                if (element is LcArc)
                {
                    var arc = (LcArc)element;
                    this.ArcStart = arc.Startp;
                    this.ArcEnd = arc.Endp;
                    this.ArcCenter = arc.Center;
                    this.ArcStartAngle = arc.StartAngle;
                    this.ArcEndAngle = arc.EndAngle;
                    this.ArcMoveAngle = arc.MoveAngle;
                    this.ArcLength = arc.ArcLength;
                    goto Step1;
                }
                else {
                    goto Step0;
                }
            }
            Step1:
            var step1 = SetCurStep(curMethod, 1);
            var result1 = await PointInputer.Execute(step1.Options);
            if (PointInputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result1 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result1.ValueX == null)
            {
                goto Step1;
            }
            else {
                this.midPoint = (Vector2)result1.ValueX;
                CreateDimElement();
            }
        End:
            this.EndCreating();

        }
        private void CreateDimElement()
        {
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("DIMARC");
            var dimArc = doc.CreateObject<DimArc>();
            dimArc.ArcStart = this.ArcStart;
            dimArc.ArcEnd = this.ArcEnd;
            dimArc.ArcCenter = this.ArcCenter;
            dimArc.mppoint = this.midPoint;
            dimArc.ArcStartAngle = this.ArcStartAngle;
            dimArc.ArcEndAngle = this.ArcEndAngle;
            dimArc.ArcMoveAngle = this.ArcMoveAngle;
            dimArc.ArcLength = this.ArcLength;
            dimArc.LoadDimArcProperty();

            LcText text = doc.CreateObject<LcText>();
            text.Start = dimArc.dimarcMidp;
            text.TextStart = dimArc.dimarcMidp;
            text.Heigh = 40;// this.raduis * 2 / 20 < 1 ? 1 : Math.Round(this.raduis * 2 / 20);
            text.Text = (dimArc.MoveAngle).ToString("0.00");
            text.Rotate = 180 / Math.PI * (dimArc.Endp - dimArc.Startp).Angle();
            text.Alignment = "左对齐";
            text.Widthfactor = 1;
            text.Tilt = 0;

            dimArc.Dimtext = text;
            doc.ModelSpace.InsertElement(dimArc);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }
       


        /// <summary>
        /// 对一个坐标点按照一个中心进行旋转
        /// </summary>
        /// <param name="center">中心点</param>
        /// <param name="p1">要旋转的点</param>
        /// <param name="angle">旋转角度，笛卡尔直角坐标</param>
        /// <returns></returns>
        private Vector2 PointRotate(Vector2 center, Vector2 p1, double angle)
        {
            Vector2 tmp = new Vector2();
            double angleHude = angle * Math.PI / 180;/*角度变成弧度*/
            double x1 = (p1.X - center.X) * Math.Cos(angleHude) + (p1.Y - center.Y) * Math.Sin(angleHude) + center.X;
            double y1 = -(p1.X - center.X) * Math.Sin(angleHude) + (p1.Y - center.Y) * Math.Cos(angleHude) + center.Y;
            tmp.X = (int)x1;
            tmp.Y = (int)y1;
            return tmp;
        }
        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }



        public override void CreateElement(LcElement element, Matrix3 matrix)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, matrix);
            }
        }
        public override void CreateElement(LcElement element, Vector2 basePoint, double scaleFactor)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, basePoint, scaleFactor);
            }

        }
        public override void CreateElement(LcElement element, Vector2 basePoint, Vector2 scaleVector)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, basePoint, scaleVector);
            }

        }
        public override void Draw(SKCanvas canvas, LcElement element, Matrix3 matrix)
        {
            var dimarc = element as DimArc;
            var center = this.vportRt.ConvertWcsToScr(dimarc.Center).ToSKPoint();
            var end = this.vportRt.ConvertWcsToScr(dimarc.Endp).ToSKPoint();

            var ArcStart= this.vportRt.ConvertWcsToScr(dimarc.ArcStart).ToSKPoint();
            var ArcEnd = this.vportRt.ConvertWcsToScr(dimarc.ArcEnd).ToSKPoint();
            var Startp = this.vportRt.ConvertWcsToScr(dimarc.Startp).ToSKPoint();
            var Endp = this.vportRt.ConvertWcsToScr(dimarc.Endp).ToSKPoint();

            double radius = Math.Sqrt(Math.Pow(center.X - end.X, 2) + Math.Pow(center.Y - end.Y, 2));
            float x1 = (float)(center.X - radius);
            float y1 = (float)(center.Y - radius);
            float x2 = (float)(center.X + radius);
            float y2 = (float)(center.Y + radius);
            SKRect skrect = new SKRect(x1, y1, x2, y2);
            var pen = this.GetDrawPen(element);
            if (pen == Constants.defaultPen)
            {
                //TODO:这里可以考虑将实线用颜色做KEY，对SKPaint进行缓存
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {
                    canvas.DrawLine(ArcStart, Startp, elePen);
                    canvas.DrawLine(ArcEnd, Endp, elePen);
                    canvas.DrawArc(skrect, (float)dimarc.StartAngle, (float)dimarc.MoveAngle, false, elePen);
                }
            }
            else
            {
                canvas.DrawLine(ArcStart, Startp, pen);
                canvas.DrawLine(ArcEnd, Endp, pen);
                canvas.DrawArc(skrect, (float)dimarc.StartAngle, (float)dimarc.MoveAngle, false, pen);
            }
            var eleAction = (dimarc.Dimtext.RtAction as ElementAction);
            dimarc.Dimtext.Start = dimarc.dimarcMidp;
            dimarc.Dimtext.Rotate = 180 / Math.PI * (dimarc.Endp - dimarc.Startp).Angle();
            dimarc.Dimtext.Text = (dimarc.MoveAngle).ToString("0.00");
            eleAction.SetViewport(this.vportRt).Draw(canvas, dimarc.Dimtext, new Matrix3());
        }


        public override void DrawAuxLines(SKCanvas canvas)
        {
            var mp = this.vportRt.PointerMovedPosition.ToVector2d();
            var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
            if (this.ArcCenter != null)
            {
                DimArc dimArc = new DimArc();
                dimArc.ArcStart = this.ArcStart;
                dimArc.ArcEnd = this.ArcEnd;
                dimArc.ArcCenter = this.ArcCenter;
                dimArc.mppoint = wcs_mp;
                dimArc.ArcStartAngle = this.ArcStartAngle;
                dimArc.ArcEndAngle = this.ArcEndAngle;
                dimArc.ArcMoveAngle = this.ArcMoveAngle;
                dimArc.LoadDimArcProperty();
                DrawAuxLine(canvas, dimArc.ArcStart, dimArc.Startp);
                DrawAuxLine(canvas, dimArc.ArcEnd, dimArc.Endp);
                DrawAuxArc(canvas, dimArc);

                LcText text = new LcText();
                text.Start = dimArc.dimarcMidp;
                text.TextStart = dimArc.dimarcMidp;
                text.Heigh = 4;// this.raduis * 2 / 20 < 1 ? 1 : Math.Round(this.raduis * 2 / 20);
                text.Text = (dimArc.MoveAngle).ToString("0.00");
                text.Rotate = 180 / Math.PI * (dimArc.Endp - dimArc.Startp).Angle();
                text.Alignment = "左对齐";
                text.Widthfactor = 1;
                text.Tilt = 0;
                text.Typeface = "宋体";

                dimArc.Dimtext = text;
                this.vportRt.DrawText(dimArc.dimarcMidp, dimArc.Dimtext.TextStart, dimArc.Dimtext.Heigh, 180 / Math.PI * (dimArc.Startp - dimArc.Endp).Angle(), dimArc.Dimtext.Text, dimArc.Dimtext.Tilt,
                    dimArc.Dimtext.Typeface, dimArc.Dimtext.Widthfactor, dimArc.Dimtext.Alignment, new Matrix3(), canvas, Runtime.Constants.draggingPen);
            }
        }

        private void DrawAuxArc(SKCanvas canvas, DimArc dimarc)
        {
            var center = this.vportRt.ConvertWcsToScr(dimarc.Center).ToSKPoint();
            var start = this.vportRt.ConvertWcsToScr(dimarc.Startp).ToSKPoint();
            var end = this.vportRt.ConvertWcsToScr(dimarc.Endp).ToSKPoint();
            //辅助参考线
            //canvas.DrawLine(start, center, Constants.auxElementPen);
            //canvas.DrawLine(end, center, Constants.auxElementPen);

            double radius = Math.Sqrt(Math.Pow(center.X - end.X, 2) + Math.Pow(center.Y - end.Y, 2));
            float x1 = (float)(center.X - radius);
            float y1 = (float)(center.Y - radius);
            float x2 = (float)(center.X + radius);
            float y2 = (float)(center.Y + radius);
            SKRect skrect = new SKRect(x1, y1, x2, y2);
            
            canvas.DrawArc(skrect, (float)dimarc.StartAngle, (float)dimarc.MoveAngle, false, Constants.auxElementPen);
        }

        private void DrawAuxLine(SKCanvas canvas, Vector2 p0, Vector2 p1)
        {
            var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(sk_pre, sk_p, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });
            //辅助曲线的颜色，包括辅助长度，辅助角度等
        }

        #region Grip
        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var dimarc = element as DimArc;
            var grips = new List<ControlGrip>();
            
            return grips.ToArray();
        }
        private string _gripName;
        private Vector2 _position;
        private DimArc _dimarc;

        public override void SetDragGrip(LcElement element, string gripName, Vector2 position, bool isEnd)
        {
            _dimarc = element as DimArc;

            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                
            }
        }


        public override void DrawDragGrip(SKCanvas canvas)
        {
            
        }

        #endregion

        public override List<PropertyObserver> GetPropertyObservers()
        {
            return new List<PropertyObserver>()
            {
                
            };
        }
    }
}
